package com.yuhan.common.config;

import com.github.tobato.fastdfs.domain.FileInfo;
import com.github.tobato.fastdfs.domain.StorePath;
import com.github.tobato.fastdfs.proto.storage.DownloadByteArray;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;

/**
 * @program: yuhan-common
 * @description: 文件上传
 * @author: hejing
 * @create: 2019-07-04 16:18
 **/
@Component
public class FastDFSClientWrapper {
    private final Logger logger = LoggerFactory.getLogger(FastDFSClientWrapper.class);

    @Autowired
    private FastFileStorageClient storageClient;

    @Value("${fdfs.base.adress}")
    private String fsBaseAdress;


    /**
     * 上传文件
     *
     * @param file 文件对象
     * @return 文件访问地址
     * @throws IOException
     */
    public String uploadFile(MultipartFile file) throws IOException {
        InputStream input = file.getInputStream();
        long size = file.getSize();
        String extension = FilenameUtils.getExtension(file.getOriginalFilename());
        StorePath storePath = storageClient.uploadFile(input, size, extension, null);
        if (input != null) {
            IOUtils.closeQuietly(input);
        }
        return getResAccessUrl(storePath);
    }

    /**
     * 普通的文件上传
     *
     * @param file
     * @return
     * @throws IOException
     */
    public String uploadFile(File file) throws IOException {
        FileInputStream inputStream = new FileInputStream(file);
        StorePath path = storageClient.uploadFile(inputStream, file.length(),
                FilenameUtils.getExtension(file.getName()), null);
        return getResAccessUrl(path);
    }

    /**
     * 将一段字符串生成一个文件上传
     *
     * @param content       文件内容
     * @param fileExtension
     * @return
     */
    public String uploadFile(String content, String fileExtension) {
        byte[] buff = content.getBytes(Charset.forName("UTF-8"));
        ByteArrayInputStream stream = new ByteArrayInputStream(buff);
        StorePath storePath = storageClient.uploadFile(stream, buff.length, fileExtension, null);
        return getResAccessUrl(storePath);
    }

    /**
     * 封装图片完整URL地址
     */
    private String getResAccessUrl(StorePath storePath) {
        String fileUrl = fsBaseAdress + "/" + storePath.getFullPath();
        return fileUrl;
    }

    /**
     * 删除文件
     *
     * @param fileUrl 文件访问地址
     * @return
     */
    public void deleteFile(String fileUrl) throws Exception {
        if (StringUtils.isEmpty(fileUrl)) {
            return;
        }
        StorePath storePath = StorePath.praseFromUrl(fileUrl);
        String group = storePath.getGroup();
        String path = storePath.getPath();
        storageClient.deleteFile(group, path);
    }

    /**
     * 查询文件信息
     */
    public FileInfo queryFileInfo(String fileUrl) {
        StorePath storePath = StorePath.praseFromUrl(fileUrl);
        String group = storePath.getGroup();
        String path = storePath.getPath();
        return storageClient.queryFileInfo(group, path);
    }

    /**
     * 上传图片并同时生成一个缩略图
     */
    public StorePath uploadImageAndCrtThumbImage(MultipartFile file) throws IOException {
        InputStream input = file.getInputStream();
        long size = file.getSize();
        String extension = FilenameUtils.getExtension(file.getOriginalFilename());
        StorePath storePath = storageClient.uploadImageAndCrtThumbImage(input, size, extension, null);
        if (input != null) {
            IOUtils.closeQuietly(input);
        }
        return storePath;
    }

    /**
     * 下载整个文件
     */
    public String download(String fileUrl) {
        StorePath storePath = StorePath.praseFromUrl(fileUrl);
        String group = storePath.getGroup();
        String path = storePath.getPath();
        byte[] bytes = storageClient.downloadFile(group, path, new DownloadByteArray());
        try {
            String s = IOUtils.toString(bytes, "utf-8");
            return s;
        } catch (IOException e) {
            throw new IllegalStateException(e.getMessage());
        }
    }


    public String genToken(String filepath, String key, int time) {
        String token = "";
        String callPath = filepath.trim();
        callPath = callPath.substring(callPath.indexOf("group") + 7);
        if (!StringUtils.isEmpty(callPath)) {
            try {
                token = callPath + key + time;
                token = new String(token.getBytes(), "UTF-8");
                token = hashKeyForDisk(token);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return token;
    }

    /**
     * 字符串hash算法
     *
     * @param key
     * @return
     */
    public static String hashKeyForDisk(String key) {
        String cacheKey;
        try {
            final MessageDigest mDigest = MessageDigest.getInstance("MD5");
            mDigest.update(key.getBytes());
            cacheKey = bytesToHexString(mDigest.digest());
        } catch (NoSuchAlgorithmException e) {
            cacheKey = String.valueOf(key.hashCode());
        }
        return cacheKey;
    }

    private static String bytesToHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(0xFF & bytes[i]);
            if (hex.length() == 1) {
                sb.append('0');
            }
            sb.append(hex);
        }
        return sb.toString();
    }

    /**
     * 获取精确到秒的时间戳
     *
     * @return
     */
    public int getSecondTimestamp(Date date) {
        if (null == date) {
            return 0;
        }
        String timestamp = String.valueOf(date.getTime());
        int length = timestamp.length();
        if (length > 3) {
            return Integer.valueOf(timestamp.substring(0, length - 3));
        } else {
            return 0;
        }
    }
}
